Skip to content

[Pune] Kashif Shaik - Subm#1208

Open
kasheww-nutt wants to merge 4 commits intonasscomAI:mainfrom
kasheww-nutt:participant/kashifshaik-pune
Open

[Pune] Kashif Shaik - Subm#1208
kasheww-nutt wants to merge 4 commits intonasscomAI:mainfrom
kasheww-nutt:participant/kashifshaik-pune

Conversation

@kasheww-nutt
Copy link
Copy Markdown

No description provided.

Copilot AI review requested due to automatic review settings April 20, 2026 04:23
@github-actions
Copy link
Copy Markdown

👋 Hi there, participant! Thanks for joining our Vibe Coding Session!

We're reviewing your PR for the 4 User Cases. Once your submission is validated and merged, you'll be awarded your completion badge! 🏆

Next Steps:

  • Make sure all 4 UCs are finished.
  • Ensure your commit messages match the required format.
  • Good luck!

@kasheww-nutt kasheww-nutt changed the title [Pune] Kashif Shaik - Vibe Coding Submission [Pune] Kashif Shaik - Subm Apr 20, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR submits the completed “Vibe Coding Workshop” deliverables for Pune across four use-cases (UC-0A/0B/0C/X), adding agent specs (agents.md), skill specs (skills.md), runnable Python implementations, and generated outputs (CSVs/TXT).

Changes:

  • Implemented Python CLIs for UC-0A (complaint classification), UC-0B (policy summarization), UC-0C (growth computation), and UC-X (policy Q&A).
  • Added/filled agents.md + skills.md for all UCs with enforcement rules and behaviors.
  • Added generated artifacts: results_pune.csv, summary_hr_leave.txt, growth_output.csv, and filled the submission PR template.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
uc-x/skills.md Defines document retrieval + Q&A skills for UC-X.
uc-x/app.py Implements a CLI Q&A flow (currently via hard-coded answer mapping + refusal template).
uc-x/agents.md Defines UC-X single-source + refusal enforcement rules.
uc-0c/skills.md Defines dataset loading + growth computation skills for UC-0C.
uc-0c/growth_output.csv Adds sample MoM growth output for a ward/category.
uc-0c/app.py Implements CSV loading + growth calculation CLI.
uc-0c/agents.md Defines UC-0C enforcement rules (no aggregation, null handling, formula transparency).
uc-0b/summary_hr_leave.txt Adds the produced HR leave policy summary output.
uc-0b/skills.md Defines policy retrieval + summarization skills for UC-0B.
uc-0b/app.py Implements policy file read + summary writer CLI (currently hard-coded summary).
uc-0b/agents.md Defines UC-0B compliance-focused summarization enforcement rules.
uc-0a/skills.md Defines complaint classification + batch processing skills for UC-0A.
uc-0a/results_pune.csv Adds generated classification results for Pune test set.
uc-0a/classifier.py Implements keyword-based complaint classification + batch CSV writer CLI.
uc-0a/agents.md Defines UC-0A taxonomy/priority/justification enforcement rules.
.github/PULL_REQUEST_TEMPLATE/submission.md Fills in the workshop submission template for the participant.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread uc-x/app.py
Comment on lines +9 to +11
REFUSAL_TEMPLATE = """This question is not covered in the available policy documents
(policy_hr_leave.txt, policy_it_acceptable_use.txt, policy_finance_reimbursement.txt).
Please contact the relevant team for guidance."""
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The refusal template here is multi-line, but uc-x/agents.md enforcement requires an exact, single-line template (with the document list in parentheses). As written, the app will not return the exact template specified by the agent rules—please align REFUSAL_TEMPLATE and the agents.md template byte-for-byte.

Suggested change
REFUSAL_TEMPLATE = """This question is not covered in the available policy documents
(policy_hr_leave.txt, policy_it_acceptable_use.txt, policy_finance_reimbursement.txt).
Please contact the relevant team for guidance."""
REFUSAL_TEMPLATE = "This question is not covered in the available policy documents (policy_hr_leave.txt, policy_it_acceptable_use.txt, policy_finance_reimbursement.txt). Please contact the relevant team for guidance."

Copilot uses AI. Check for mistakes.
Comment thread uc-0c/app.py
Comment on lines +38 to +41
filtered = [row for row in data if row['ward'] == ward and row['category'] == category]

# Sort by period
filtered.sort(key=lambda x: x['period'])
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compute_growth indexes rows with row['ward'] / row['category'] / row['period'] without validating the CSV headers first. If a user passes a malformed CSV, this will raise KeyError mid-run. Consider validating required columns once in load_dataset (or before filtering) and failing fast with a clear error.

Copilot uses AI. Check for mistakes.
Comment thread uc-0c/app.py
Comment on lines +54 to +56
if growth_type == "MoM":
if prev_spend is None:
growth_val = "n/a (First Period)"
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--growth-type is documented as "MoM or YoY", but compute_growth only has logic under if growth_type == "MoM" and otherwise silently leaves every row as n/a. Please either implement YoY or validate --growth-type and exit with a clear error for unsupported values.

Copilot uses AI. Check for mistakes.
Comment thread uc-0a/classifier.py
Comment on lines +13 to +19
desc = row.get('description', '').lower()
complaint_id = row.get('complaint_id', 'Unknown')

# 1. Determine Category
category = "Other"
flag = ""

Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

classify_complaint doesn't implement the documented error handling for missing/empty descriptions (skills.md requires reason "Missing description" with NEEDS_REVIEW). With an empty description this currently produces a generic reason that claims the description mentions "other". Please add an early return for missing/blank description that matches the defined behavior.

Suggested change
desc = row.get('description', '').lower()
complaint_id = row.get('complaint_id', 'Unknown')
# 1. Determine Category
category = "Other"
flag = ""
complaint_id = row.get('complaint_id', 'Unknown')
raw_desc = row.get('description', '')
if raw_desc is None or not str(raw_desc).strip():
return {
"complaint_id": complaint_id,
"category": "Other",
"priority": "Standard",
"reason": "Missing description",
"flag": "NEEDS_REVIEW"
}
desc = str(raw_desc).lower()
# 1. Determine Category
category = "Other"
flag = ""

Copilot uses AI. Check for mistakes.
Comment thread uc-0b/app.py
Produces a compliant summary of the policy document.
Ensures every numbered clause is accounted for and conditions are preserved.
"""
# Ground truth mapping based on the workshop instructions
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

summarize_policy ignores the content parameter and always returns a hard-coded summary. This makes the --input argument misleading and will produce incorrect output if the input policy file changes. Please generate the summary from content (or validate the input is the expected document and refuse otherwise).

Suggested change
# Ground truth mapping based on the workshop instructions
normalized_content = " ".join(content.split()).lower()
required_markers = [
"hr leave policy",
"hr-pol-001",
"14 calendar days in advance",
"verbal approval is not valid",
"loss of pay",
"maximum of 5 unused annual leave days",
"january and march of the following year",
"3 or more consecutive days requires a medical certificate",
"public holiday or annual leave period requires a medical certificate",
"department head and the hr director",
"30 continuous days requires approval from the municipal commissioner",
"leave encashment during service is not permitted"
]
missing_markers = [marker for marker in required_markers if marker not in normalized_content]
if missing_markers:
raise ValueError(
"Unsupported policy document: input does not match the expected HR Leave Policy "
"(Ref: HR-POL-001), so a fixed summary cannot be generated safely."
)
# Ground truth mapping for the validated HR Leave Policy document

Copilot uses AI. Check for mistakes.
Comment thread uc-x/app.py
Implementation based on RICE → agents.md → skills.md workflow.
"""
import argparse
import os
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os is imported but never used in this file. Please remove the unused import to avoid lint/runtime warnings and keep dependencies clear.

Suggested change
import os

Copilot uses AI. Check for mistakes.
Comment thread uc-0a/classifier.py
Comment on lines +58 to +60
reason = f"Classified as {category} because description mentions '{category.lower()}'; prioritized as {priority} due to words like '{', '.join(trigger_words) if trigger_words else 'none'}'. "
# Ensure exactly one sentence (very simple)
reason = reason.strip()
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason string claims the description mentions '{category.lower()}', but the exact category phrase often isn't present in the text (e.g., "Road Damage" vs "road surface cracked"). This violates the requirement to cite specific words from the description. Please capture and cite the actual triggering keyword(s) used for classification.

Copilot uses AI. Check for mistakes.
Comment thread uc-0c/app.py
Comment on lines +54 to +58
if growth_type == "MoM":
if prev_spend is None:
growth_val = "n/a (First Period)"
formula = "n/a"
elif current_spend is None:
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "first period" check uses prev_spend is None, but prev_spend is also set to None whenever a row has NULL actual_spend. That causes the period after a NULL to be incorrectly labeled as the first period and growth to be computed/flagged incorrectly. Consider tracking a separate first-row flag and adding an explicit branch for "previous period spend is NULL".

Copilot uses AI. Check for mistakes.
Comment thread uc-0c/app.py
Comment on lines +79 to +80
prev_spend = current_spend

Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prev_spend = current_spend updates the previous value even when current_spend is NULL, which makes subsequent periods lose the last valid baseline. Please avoid overwriting prev_spend with NULL (or keep both prev_spend and prev_spend_valid), so the next row can be correctly flagged as "cannot compute due to previous NULL".

Copilot uses AI. Check for mistakes.
Comment thread uc-x/app.py
Comment on lines +7 to 42

# Refusal Template
REFUSAL_TEMPLATE = """This question is not covered in the available policy documents
(policy_hr_leave.txt, policy_it_acceptable_use.txt, policy_finance_reimbursement.txt).
Please contact the relevant team for guidance."""

# Hardcoded logic for demo purposes (simulating a high-precision retrieval system)
ANSWERS = {
"can i carry forward unused annual leave?":
"As per policy_hr_leave.txt Section 2.6, employees may carry forward a maximum of 5 unused annual leave days to the following calendar year. Any days above 5 are forfeited on 31 December.",

"can i install slack on my work laptop?":
"As per policy_it_acceptable_use.txt Section 2.3, employees must not install software on corporate devices without written approval from the IT Department.",

"what is the home office equipment allowance?":
"As per policy_finance_reimbursement.txt Section 3.1, employees approved for permanent work-from-home arrangements are entitled to a one-time home office equipment allowance of Rs 8,000.",

"can i use my personal phone for work files from home?":
"As per policy_it_acceptable_use.txt Section 3.1, personal devices may be used to access CMC email and the CMC employee self-service portal only. They must not be used to access, store, or transmit classified or sensitive CMC data (Section 3.2).",

"can i claim da and meal receipts on the same day?":
"As per policy_finance_reimbursement.txt Section 2.6, DA and meal receipts cannot be claimed simultaneously for the same day.",

"who approves leave without pay?":
"As per policy_hr_leave.txt Section 5.2, Leave Without Pay (LWP) requires approval from the Department Head and the HR Director. Manager approval alone is not sufficient.",
}

def answer_question(question: str) -> str:
q = question.lower().strip().rstrip('?') + '?'
# Simple lookup
for key, value in ANSWERS.items():
if key in q or q in key:
return value

return REFUSAL_TEMPLATE

Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The UC-X app currently hard-codes answers in the ANSWERS dict and never reads the policy documents listed in uc-x/README.md / skills.md. This means updates to the policy text files won’t be reflected and the system isn’t actually doing document-grounded retrieval. Please load and parse the policy files at runtime (even with simple section indexing) and derive answers from that source instead of hardcoding responses.

Suggested change
# Refusal Template
REFUSAL_TEMPLATE = """This question is not covered in the available policy documents
(policy_hr_leave.txt, policy_it_acceptable_use.txt, policy_finance_reimbursement.txt).
Please contact the relevant team for guidance."""
# Hardcoded logic for demo purposes (simulating a high-precision retrieval system)
ANSWERS = {
"can i carry forward unused annual leave?":
"As per policy_hr_leave.txt Section 2.6, employees may carry forward a maximum of 5 unused annual leave days to the following calendar year. Any days above 5 are forfeited on 31 December.",
"can i install slack on my work laptop?":
"As per policy_it_acceptable_use.txt Section 2.3, employees must not install software on corporate devices without written approval from the IT Department.",
"what is the home office equipment allowance?":
"As per policy_finance_reimbursement.txt Section 3.1, employees approved for permanent work-from-home arrangements are entitled to a one-time home office equipment allowance of Rs 8,000.",
"can i use my personal phone for work files from home?":
"As per policy_it_acceptable_use.txt Section 3.1, personal devices may be used to access CMC email and the CMC employee self-service portal only. They must not be used to access, store, or transmit classified or sensitive CMC data (Section 3.2).",
"can i claim da and meal receipts on the same day?":
"As per policy_finance_reimbursement.txt Section 2.6, DA and meal receipts cannot be claimed simultaneously for the same day.",
"who approves leave without pay?":
"As per policy_hr_leave.txt Section 5.2, Leave Without Pay (LWP) requires approval from the Department Head and the HR Director. Manager approval alone is not sufficient.",
}
def answer_question(question: str) -> str:
q = question.lower().strip().rstrip('?') + '?'
# Simple lookup
for key, value in ANSWERS.items():
if key in q or q in key:
return value
return REFUSAL_TEMPLATE
import re
# Refusal Template
REFUSAL_TEMPLATE = """This question is not covered in the available policy documents
(policy_hr_leave.txt, policy_it_acceptable_use.txt, policy_finance_reimbursement.txt).
Please contact the relevant team for guidance."""
POLICY_FILES = [
"policy_hr_leave.txt",
"policy_it_acceptable_use.txt",
"policy_finance_reimbursement.txt",
]
_POLICY_INDEX = None
_STOP_WORDS = {
"a", "an", "and", "are", "as", "at", "be", "by", "can", "do", "for", "from",
"how", "i", "if", "in", "is", "it", "may", "of", "on", "or", "the", "to",
"what", "when", "who", "with", "without", "my", "we", "our", "your", "same"
}
def _normalize_text(text: str) -> str:
return re.sub(r"\s+", " ", text.strip().lower())
def _tokenize(text: str) -> set:
return {
token for token in re.findall(r"[a-z0-9]+", _normalize_text(text))
if token not in _STOP_WORDS and len(token) > 1
}
def _find_policy_path(filename: str) -> str:
base_dir = os.path.dirname(os.path.abspath(__file__))
candidates = [
os.path.join(base_dir, filename),
os.path.join(os.getcwd(), filename),
]
for path in candidates:
if os.path.isfile(path):
return path
return ""
def _parse_policy_sections(filename: str, text: str) -> list:
sections = []
current_heading = "Document Overview"
current_lines = []
def flush_section():
content = "\n".join(current_lines).strip()
if not content:
return
flat_content = re.sub(r"\s+", " ", content)
sections.append({
"file": filename,
"section": current_heading,
"content": flat_content,
"tokens": _tokenize(current_heading + " " + flat_content),
})
for raw_line in text.splitlines():
line = raw_line.strip()
if not line:
continue
is_heading = (
bool(re.match(r"^(section\s+\d+(?:\.\d+)*)\b", line, flags=re.IGNORECASE)) or
bool(re.match(r"^\d+(?:\.\d+)*[\).:\-]?\s+\S+", line)) or
bool(re.match(r"^#{1,6}\s+\S+", line))
)
if is_heading:
flush_section()
if line.startswith("#"):
current_heading = line.lstrip("#").strip()
else:
current_heading = line
current_lines = []
else:
current_lines.append(line)
flush_section()
if not sections and text.strip():
flat_text = re.sub(r"\s+", " ", text.strip())
sections.append({
"file": filename,
"section": "Document Overview",
"content": flat_text,
"tokens": _tokenize(flat_text),
})
return sections
def _load_policy_index() -> list:
global _POLICY_INDEX
if _POLICY_INDEX is not None:
return _POLICY_INDEX
index = []
for filename in POLICY_FILES:
path = _find_policy_path(filename)
if not path:
continue
with open(path, "r", encoding="utf-8") as policy_file:
index.extend(_parse_policy_sections(filename, policy_file.read()))
_POLICY_INDEX = index
return _POLICY_INDEX
def _best_section_match(question: str):
query_tokens = _tokenize(question)
if not query_tokens:
return None
best_match = None
best_score = 0
for section in _load_policy_index():
overlap = query_tokens & section["tokens"]
score = len(overlap)
if not overlap:
continue
section_text = _normalize_text(section["section"] + " " + section["content"])
normalized_question = _normalize_text(question)
if normalized_question in section_text:
score += 5
for token in query_tokens:
if token in section_text:
score += 1
if score > best_score:
best_score = score
best_match = section
return best_match if best_score >= 3 else None
def answer_question(question: str) -> str:
match = _best_section_match(question)
if not match:
return REFUSAL_TEMPLATE
return f"As per {match['file']} {match['section']}, {match['content']}"

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants